from multiprocessing import cpu_count
from os import getcwd
from os.path import join
from argparse import ArgumentParser
from configparser import ConfigParser, NoSectionError

from src.logger import Logger


class Config:
    """
    获取项目配置 [单例]

    1. CLI 参数列表
    - `-c, --conf` 配置文件路径 (`default`: `conf.ini`)
    """

    _instance = None
    _has_init = False

    def __new__(cls):
        if not cls._instance:
            cls._instance = super(Config, cls).__new__(cls)
        return cls._instance

    def __init__(self) -> None:
        if self._has_init:
            return

        self._has_init = True
        self.cwd = getcwd()
        self.__parse_args()
        self.__parse_conf()

    def __parse_args(self) -> None:
        parser = ArgumentParser()
        parser.add_argument("-c", "--conf", default="conf.ini", help="配置文件路径")
        self.args = parser.parse_args()

    def __parse_conf(self) -> None:
        self.conf = ConfigParser()
        Logger.Info(f"loading config file, pwd: {getcwd()} file: { self.args.conf}")
        self.conf.read(self.args.conf)

        try:
            self.app = App(self.conf)
            self.matlab = Matlab(self.cwd, self.conf)
            self.rabbit_mq = RabbitMQ(self.conf)
            self.report = Report(self.conf)

            self.lab_mimo_decode = Lab("lab_mimo_decode", self.conf)
            self.lab_mimo_plot = Lab("lab_mimo_plot", self.conf)
        except NoSectionError as e:
            Logger.Error(f"config file parse error: `{e.message}`")
            exit(1)


class App:
    def __init__(self, config: ConfigParser) -> None:
        max_workers = config.getint("app", "max_workers")
        cpu_cores = cpu_count()
        Logger.Info(f"{cpu_cores} cores")
        if max_workers > 0:
            self.max_workers: int = min(max_workers, cpu_cores)
        else:
            self.max_workers: int = max(cpu_cores + max_workers, 1)


class Report:
    def __init__(self, config: ConfigParser) -> None:
        self.queue = config.get("report", "queue")


class Matlab:
    def __init__(self, cwd: str, config: ConfigParser) -> None:
        self.assets_dir = join(cwd, config.get("matlab", "assets_dir"))
        self.lib_path = join(cwd, config.get("matlab", "lib_path"))


class RabbitMQ:
    def __init__(self, config: ConfigParser) -> None:
        self.host = config.get("rabbit_mq", "host")
        self.port = config.get("rabbit_mq", "port")
        self.username = config.get("rabbit_mq", "username")
        self.password = config.get("rabbit_mq", "password")


class Lab:
    def __init__(self, lab_key: str, config: ConfigParser) -> None:
        self.mock = config.get(lab_key, "mock") == "True"
        self.queue = config.get(lab_key, "queue")
        self.app_id = config.get(lab_key, "app_id")
        self.weight = config.getint(lab_key, "weight")
